#include <iostream>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cassert>
#include "FileWriter.hpp"
#include <bits/types/FILE.h>
#include "Event.hpp"


struct CFileWriter::FileWriterImpl
{
    FileWriterImpl(const std::string& filename)
    {
        assert(m_fp = fopen(filename.c_str(),"wb"));
    }
    ~FileWriterImpl()
    {
        std::fclose(m_fp);
    }
    FileWriterImpl(const FileWriterImpl&) = delete;
    FileWriterImpl& operator=(const FileWriterImpl&) = delete;
    FileWriterImpl(const FileWriterImpl&&) = delete;
    FileWriterImpl& operator=(const FileWriterImpl&&) = delete;
    FILE * m_fp;

    int WriteAtBegin(void* data,int length) {
        fseek(m_fp, 0,SEEK_SET);
        return fwrite(data,sizeof(char),length,m_fp);
    }

    int WriteAtEnd(void* data,int length) {
        fseek(m_fp, 0,SEEK_END);
        int rc = fwrite(data,sizeof(char),length,m_fp);
        fwrite("\n",sizeof(char),1,m_fp);
        return rc + 1;
    }
    

};

CFileWriter::CFileWriter(const std::string& filename,StrategyTag tag):
    m_pImpl(new FileWriterImpl(filename))
{
        if(tag == StrategyTag::NORMAL){
            m_pStrategy = new NormalStrategy();
        }else if(tag == StrategyTag::LAZY){
            m_pStrategy = new LazyStrategy();
        }
}

CFileWriter::~CFileWriter()
{   
        delete m_pImpl;
        if(m_pStrategy != nullptr){
            delete m_pStrategy;
        }
}

// IWrite Interface
int CFileWriter::WriteAtBegin(void* data,int length) {
    m_pStrategy->OnWriteAt(0,data,length);
    m_pImpl->WriteAtBegin(data,length);
    std::cout << "write" << length << " byte at file begin" << std::endl;
    return length;
}

int CFileWriter::WriteAt(int pos,void* data,int length) {
    std::cout << "write" << length << " byte at " << pos << std::endl;
    OnWrite(pos, length);
    return length;
}

int CFileWriter::WriteEnd(void* data,int length) {
    m_pImpl->WriteAtEnd(data, length);
    std::cout << "write" << length << " byte at file end" << std::endl;
    return length;
}
